package com.netease.nim.uikit.session.fragment;

import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.netease.nim.uikit.CustomPushContentProvider;
import com.netease.nim.uikit.NimUIKit;
import com.netease.nim.uikit.R;
import com.netease.nim.uikit.cache.RobotInfoCache;
import com.netease.nim.uikit.common.fragment.TFragment;
import com.netease.nim.uikit.contact.ait.AitContactSelectorActivity;
import com.netease.nim.uikit.contact.ait.AitedContacts;
import com.netease.nim.uikit.session.SessionCustomization;
import com.netease.nim.uikit.session.actions.BaseAction;
import com.netease.nim.uikit.session.actions.ImageAction;
import com.netease.nim.uikit.session.actions.LocationAction;
import com.netease.nim.uikit.session.actions.VideoAction;
import com.netease.nim.uikit.session.constant.Extras;
import com.netease.nim.uikit.session.module.Container;
import com.netease.nim.uikit.session.module.ModuleProxy;
import com.netease.nim.uikit.session.module.input.InputPanel;
import com.netease.nim.uikit.session.module.input.MessageEditWatcher;
import com.netease.nim.uikit.session.module.list.MessageListPanelEx;
import com.netease.nimlib.sdk.NIMClient;
import com.netease.nimlib.sdk.Observer;
import com.netease.nimlib.sdk.RequestCallback;
import com.netease.nimlib.sdk.friend.FriendService;
import com.netease.nimlib.sdk.msg.MessageBuilder;
import com.netease.nimlib.sdk.msg.MsgService;
import com.netease.nimlib.sdk.msg.MsgServiceObserve;
import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum;
import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum;
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
import com.netease.nimlib.sdk.msg.model.CustomMessageConfig;
import com.netease.nimlib.sdk.msg.model.IMMessage;
import com.netease.nimlib.sdk.msg.model.MessageReceipt;
import com.netease.nimlib.sdk.robot.model.NimRobotInfo;
import com.netease.nimlib.sdk.robot.model.RobotMsgType;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 聊天界面基类
 * <p/>
 * Created by huangjun on 2015/2/1.
 */
public class MessageFragment extends TFragment implements ModuleProxy {

    private View rootView;

    private SessionCustomization customization;

    protected static final String TAG = "MessageActivity";

    // 聊天对象
    protected String sessionId; // p2p对方Account或者群id

    protected SessionTypeEnum sessionType;

    // modules
    protected InputPanel inputPanel;
    protected MessageListPanelEx messageListPanel;

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        parseIntent();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.nim_message_fragment, container, false);
        return rootView;
    }

    /**
     * ***************************** life cycle *******************************
     */

    @Override
    public void onPause() {
        super.onPause();

        NIMClient.getService(MsgService.class).setChattingAccount(MsgService.MSG_CHATTING_ACCOUNT_NONE,
                SessionTypeEnum.None);
        inputPanel.onPause();
        messageListPanel.onPause();
    }

    @Override
    public void onResume() {
        super.onResume();
        messageListPanel.onResume();
        NIMClient.getService(MsgService.class).setChattingAccount(sessionId, sessionType);
        getActivity().setVolumeControlStream(AudioManager.STREAM_VOICE_CALL); // 默认使用听筒播放
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        messageListPanel.onDestroy();
        registerObservers(false);
        if (inputPanel != null) {
            inputPanel.onDestroy();
        }
        AitedContacts.getInstance().clearAitContact();
    }

    public boolean onBackPressed() {
        if (inputPanel.collapse(true)) {
            return true;
        }

        if (messageListPanel.onBackPressed()) {
            return true;
        }
        return false;
    }

    public void refreshMessageList() {
        messageListPanel.refreshMessageList();
    }

    // inputPanel 文本输入框监听
    MessageEditWatcher watcher = new MessageEditWatcher() {
        @Override
        public void afterTextChanged(Editable editable, int start, int count) {
            if (count <= 0 || editable.length() < start + count)
                return;
            CharSequence s = editable.subSequence(start, start + count);
            if (s != null && s.toString().equals("@")) {
                // 选择联系人
                if (!isChatWithRobot()) {
                    startAitContactActivity();
                }
            }
        }
    };

    // 选择 @ 联系人
    protected void startAitContactActivity() {
        AitContactSelectorActivity.start(getActivity(), null, true);
    }

    private void parseIntent() {
        sessionId = getArguments().getString(Extras.EXTRA_ACCOUNT);
        sessionType = (SessionTypeEnum) getArguments().getSerializable(Extras.EXTRA_TYPE);
        IMMessage anchor = (IMMessage) getArguments().getSerializable(Extras.EXTRA_ANCHOR);

        customization = (SessionCustomization) getArguments().getSerializable(Extras.EXTRA_CUSTOMIZATION);
        Container container = new Container(getActivity(), sessionId, sessionType, this);

        if (messageListPanel == null) {
            messageListPanel = new MessageListPanelEx(container, rootView, anchor, false, false);
        } else {
            messageListPanel.reload(container, anchor);
        }

        if (inputPanel == null) {
            inputPanel = new InputPanel(container, rootView, getActionList());
            inputPanel.setCustomization(customization);
        } else {
            inputPanel.reload(container, customization);
        }
        inputPanel.setWatcher(watcher);

        inputPanel.switchRobotMode(RobotInfoCache.getInstance().getRobotByAccount(sessionId) != null);

        registerObservers(true);

        if (customization != null) {
            messageListPanel.setChattingBackground(customization.backgroundUri, customization.backgroundColor);
        }
    }

    /**
     * ************************* 消息收发 **********************************
     */
    // 是否允许发送消息
    protected boolean isAllowSendMessage(final IMMessage message) {
        return true;
    }

    /**
     * ****************** 观察者 **********************
     */

    private void registerObservers(boolean register) {
        MsgServiceObserve service = NIMClient.getService(MsgServiceObserve.class);
        service.observeReceiveMessage(incomingMessageObserver, register);
        service.observeMessageReceipt(messageReceiptObserver, register);
    }

    /**
     * 消息接收观察者
     */
    Observer<List<IMMessage>> incomingMessageObserver = new Observer<List<IMMessage>>() {
        @Override
        public void onEvent(List<IMMessage> messages) {
            if (messages == null || messages.isEmpty()) {
                return;
            }

            messageListPanel.onIncomingMessage(messages);
            sendMsgReceipt(); // 发送已读回执
        }
    };

    private Observer<List<MessageReceipt>> messageReceiptObserver = new Observer<List<MessageReceipt>>() {
        @Override
        public void onEvent(List<MessageReceipt> messageReceipts) {
            receiveReceipt();
        }
    };


    /**
     * ********************** implements ModuleProxy *********************
     */
    @Override
    public boolean sendMessage(IMMessage message) {
        if (!isAllowSendMessage(message)) {
            return false;
        }

        message = changeToRobotMsg(message);
        appendPushConfig(message);
        final IMMessage currentMessage = message;
        // send message to server and save to db
        NIMClient.getService(MsgService.class).sendMessage(message, false).setCallback(new RequestCallback<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                boolean black = NIMClient.getService(FriendService.class).isInBlackList(currentMessage.getSessionId());
                if (black) {
                    IMMessage msg = MessageBuilder.createTipMessage(currentMessage.getSessionId(), currentMessage.getSessionType());
                    msg.setContent("你已拉黑对方，将不会收到对方的消息，取消拉黑后可恢复正常聊天");
                    CustomMessageConfig config = new CustomMessageConfig();
                    config.enablePush = false; // 不推送
                    config.enableUnreadCount = false;
                    msg.setConfig(config);
                    msg.setStatus(MsgStatusEnum.success);
                    NIMClient.getService(MsgService.class).saveMessageToLocalEx(msg, true, currentMessage.getTime() + 1000);
                }
            }

            @Override
            public void onFailed(int i) {
                if (7101 == i) {
                    IMMessage msg = MessageBuilder.createTipMessage(currentMessage.getSessionId(), currentMessage.getSessionType());
                    msg.setContent("由于对方的设置，你不能给该用户发送消息");
                    CustomMessageConfig config = new CustomMessageConfig();
                    config.enablePush = false; // 不推送
                    config.enableUnreadCount = false;
                    msg.setConfig(config);
                    msg.setStatus(MsgStatusEnum.success);
                    NIMClient.getService(MsgService.class).saveMessageToLocal(msg, true);
                }
            }

            @Override
            public void onException(Throwable throwable) {

            }
        });

        messageListPanel.onMsgSend(message);

        AitedContacts.getInstance().clearAitContact();

        return true;
    }

    // 添加机器人信息
    private IMMessage changeToRobotMsg(IMMessage message) {
        Map<String, NimRobotInfo> selectedRobots = AitedContacts.getInstance().getSelectedRobots();
        if (!selectedRobots.isEmpty()) {
            Iterator<String> keySet = selectedRobots.keySet().iterator();
            String text = message.getContent();
            String firstAccount = null;
            int firstIndex = -1;
            // 找出第一个@的账号
            while (keySet.hasNext()) {
                String account = keySet.next();
                // 查一下有没有被删除
                Pattern p = Pattern.compile("(@" + account + " )");
                Matcher matcher = p.matcher(text);
                if (matcher.find()) {
                    int index = text.indexOf(account);
                    if (firstIndex < 0 || firstIndex > index) {
                        firstAccount = account;
                        firstIndex = index;
                    }
                    continue;
                }
                keySet.remove();
            }
            if (firstAccount == null) {
                return message;
            }
            // 构建机器人content
            String robotContent = text.replaceAll("(@" + firstAccount + " )", "");
            // 使用空格代替空串，防止发送机器人空串返回14413
            if (TextUtils.isEmpty(robotContent)) {
                robotContent = " ";
            }
            // 将所有的account替换成nick，作为消息的文本
            keySet = selectedRobots.keySet().iterator();
            while (keySet.hasNext()) {
                String account = keySet.next();
                NimRobotInfo robotInfo = selectedRobots.get(account);
                String aitName = robotInfo.getName();
                text = text.replaceAll("(@" + account + " )", "@" + aitName + " ");
            }
            message = MessageBuilder.createRobotMessage(message.getSessionId(), message.getSessionType(), firstAccount, text, RobotMsgType.TEXT, robotContent, null, null);

        } else if (isChatWithRobot()) {
            if (message.getMsgType() == MsgTypeEnum.text && message.getContent() != null) {
                String content = message.getContent().equals("") ? " " : message.getContent();
                message = MessageBuilder.createRobotMessage(message.getSessionId(), message.getSessionType(), message.getSessionId(), content, RobotMsgType.TEXT, content, null, null);
            }
        }

        return message;
    }

    private boolean isChatWithRobot() {
        return RobotInfoCache.getInstance().getRobotByAccount(sessionId) != null;
    }

    private void appendPushConfig(IMMessage message) {
        CustomPushContentProvider customConfig = NimUIKit.getCustomPushContentProvider();
        if (customConfig != null) {
            String content = customConfig.getPushContent(message);
            Map<String, Object> payload = customConfig.getPushPayload(message);
            message.setPushContent(content);
            message.setPushPayload(payload);
        }
    }

    @Override
    public void onInputPanelExpand() {
        messageListPanel.scrollToBottom();
    }

    @Override
    public void shouldCollapseInputPanel() {
        inputPanel.collapse(false);
    }

    @Override
    public boolean isLongClickEnabled() {
        return !inputPanel.isRecording();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        inputPanel.onActivityResult(requestCode, resultCode, data);
        messageListPanel.onActivityResult(requestCode, resultCode, data);
    }

    // 操作面板集合
    protected List<BaseAction> getActionList() {
        List<BaseAction> actions = new ArrayList<>();
        actions.add(new ImageAction());
        actions.add(new VideoAction());
        actions.add(new LocationAction());

        if (customization != null && customization.actions != null) {
            actions.addAll(customization.actions);
        }
        return actions;
    }

    /**
     * 发送已读回执
     */
    private void sendMsgReceipt() {
        messageListPanel.sendReceipt();
    }

    /**
     * 收到已读回执
     */
    public void receiveReceipt() {
        messageListPanel.receiveReceipt();
    }
}
